]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
viewSelector: Merge SearchTab into the ViewSelector
authorJoost Verdoorn <jpverdoorn@gmail.com>
Thu, 21 Jun 2012 22:52:56 +0000 (00:52 +0200)
committerFlorian Müllner <fmuellner@gnome.org>
Mon, 20 Aug 2012 12:23:19 +0000 (14:23 +0200)
Tabs used to provide an abstraction for a page and the control used to
activate it. As the latter has now been replaced with external controls
handled directly in the viewSelector, the abstraction itself doesn't make
much sense anymore. In preparation of replacing it, move the search
handling provided by the SearchTab directly in the viewSelector.

https://bugzilla.gnome.org/show_bug.cgi?id=682109

js/ui/viewSelector.js

index 38326a59b22c130cb7b1e8ff49c455a20fb5c136..0d382a21e510bc7746cda558fff8f2760b56eb61 100644 (file)
@@ -98,11 +98,33 @@ const ViewTab = new Lang.Class({
 });
 
 
-const SearchTab = new Lang.Class({
-    Name: 'SearchTab',
-    Extends: BaseTab,
+const ViewSelector = new Lang.Class({
+    Name: 'ViewSelector',
+
+    _init : function(searchEntry, showAppsButton) {
+        this.actor = new St.BoxLayout({ name: 'viewSelector',
+                                        vertical: true });
+
+        this._showAppsButton = showAppsButton;
+        this._showAppsButton.connect('notify::checked', Lang.bind(this,
+            function() {
+                if (this._showAppsButton.checked)
+                    this._switchTab(this._appsTab);
+                else
+                    this._switchTab(this._windowsTab);
+            }));
+
+        // The page area holds the tab pages. Every page is given the
+        // area's full allocation, so that the pages would appear on top
+        // of each other if the inactive ones weren't hidden.
+        this._pageArea = new Shell.Stack();
+        this.actor.add(this._pageArea, { x_fill: true,
+                                         y_fill: true,
+                                         expand: true });
+
+        this._tabs = [];
+        this._activeTab = null;
 
-    _init: function(searchEntry) {
         this.active = false;
         this._searchPending = false;
         this._searchTimeoutId = 0;
@@ -111,8 +133,18 @@ const SearchTab = new Lang.Class({
 
         this._entry = searchEntry;
         ShellEntry.addContextMenu(this._entry);
+
         this._text = this._entry.clutter_text;
+        this._text.connect('text-changed', Lang.bind(this, this._onTextChanged));
         this._text.connect('key-press-event', Lang.bind(this, this._onKeyPress));
+        this._text.connect('key-focus-in', Lang.bind(this, function() {
+            this._searchResults.highlightDefault(true);
+        }));
+        this._text.connect('key-focus-out', Lang.bind(this, function() {
+            this._searchResults.highlightDefault(false);
+        }));
+        this._entry.connect('notify::mapped', Lang.bind(this, this._onMapped));
+        global.stage.connect('notify::key-focus', Lang.bind(this, this._onStageKeyFocusChanged));
 
         this._inactiveIcon = new St.Icon({ style_class: 'search-entry-icon',
                                            icon_name: 'edit-find',
@@ -123,38 +155,29 @@ const SearchTab = new Lang.Class({
         this._entry.set_secondary_icon(this._inactiveIcon);
 
         this._iconClickedId = 0;
+        this._capturedEventId = 0;
 
-        this._searchResults = new SearchDisplay.SearchResults(this._searchSystem);
-        this.parent(new St.Bin() /* Dummy */, this._searchResults.actor, _("Search"), 'edit-find');
-
-        this._text.connect('text-changed', Lang.bind(this, this._onTextChanged));
-        this._text.connect('key-press-event', Lang.bind(this, function (o, e) {
-            // We can't connect to 'activate' here because search providers
-            // might want to do something with the modifiers in activateDefault.
-            let symbol = e.get_key_symbol();
-            if (symbol == Clutter.Return || symbol == Clutter.KP_Enter) {
-                if (this._searchTimeoutId > 0) {
-                    Mainloop.source_remove(this._searchTimeoutId);
-                    this._doSearch();
-                }
-                this._searchResults.activateDefault();
-                return true;
-            }
-            return false;
-        }));
+        this._workspacesDisplay = new WorkspacesView.WorkspacesDisplay();
+        this._windowsTab = new ViewTab('windows', _("Windows"), this._workspacesDisplay.actor, 'text-x-generic');
+        this._addViewTab(this._windowsTab);
 
-        this._entry.connect('notify::mapped', Lang.bind(this, this._onMapped));
+        let appView = new AppDisplay.AllAppDisplay();
+        this._appsTab = new ViewTab('applications', _("Applications"), appView.actor, 'system-run');
+        this._addViewTab(this._appsTab);
 
-        global.stage.connect('notify::key-focus', Lang.bind(this, this._onStageKeyFocusChanged));
+        this._searchResults = new SearchDisplay.SearchResults(this._searchSystem);
+        this._searchTab = new BaseTab(new St.Bin(), this._searchResults.actor, _("Search"), 'edit-find');
+        this._addTab(this._searchTab);
 
-        this._capturedEventId = 0;
+        // Default search providers
+        // Wanda comes obviously first
+        this.addSearchProvider(new Wanda.WandaSearchProvider());
+        this.addSearchProvider(new AppDisplay.AppSearchProvider());
+        this.addSearchProvider(new AppDisplay.SettingsSearchProvider());
+        this.addSearchProvider(new PlaceDisplay.PlaceSearchProvider());
 
-        this._text.connect('key-focus-in', Lang.bind(this, function() {
-            this._searchResults.highlightDefault(true);
-        }));
-        this._text.connect('key-focus-out', Lang.bind(this, function() {
-            this._searchResults.highlightDefault(false);
-        }));
+        // Load remote search providers provided by applications
+        RemoteSearch.loadRemoteSearchProviders(Lang.bind(this, this.addSearchProvider));
 
         // Since the entry isn't inside the results container we install this
         // dummy widget as the last results container child so that we can
@@ -172,10 +195,130 @@ const SearchTab = new Lang.Class({
         this._searchResults.actor.add_actor(this._focusTrap);
 
         global.focus_manager.add_group(this._searchResults.actor);
+
+        Main.overview.connect('item-drag-begin',
+                              Lang.bind(this, this._resetShowAppsButton));
+
+        this._stageKeyPressId = 0;
+        Main.overview.connect('showing', Lang.bind(this,
+            function () {
+                this._resetShowAppsButton();
+                this._stageKeyPressId = global.stage.connect('key-press-event',
+                                                             Lang.bind(this, this._onStageKeyPress));
+            }));
+        Main.overview.connect('hiding', Lang.bind(this,
+            function () {
+                this._resetShowAppsButton();
+                if (this._stageKeyPressId != 0) {
+                    global.stage.disconnect(this._stageKeyPressId);
+                    this._stageKeyPressId = 0;
+                }
+            }));
+
+        // Public constraints which may be used to tie actors' height or
+        // vertical position to the current tab's content; as the content's
+        // height and position depend on the view selector's style properties
+        // (e.g. font size, padding, spacing, ...) it would be extremely hard
+        // and ugly to get these from the outside. While it would be possible
+        // to use position and height properties directly, outside code would
+        // need to ensure that the content is properly allocated before
+        // accessing the properties.
+        this.constrainHeight = new Clutter.BindConstraint({ source: this._pageArea,
+                                                            coordinate: Clutter.BindCoordinate.HEIGHT });
+    },
+
+    show: function() {
+        this._workspacesDisplay.show();
+
+        if (!this._workspacesDisplay.activeWorkspaceHasMaximizedWindows())
+            Main.overview.fadeOutDesktop();
+    },
+
+    zoomFromOverview: function() {
+        this._workspacesDisplay.zoomFromOverview();
+
+        if (!this._workspacesDisplay.activeWorkspaceHasMaximizedWindows())
+            Main.overview.fadeInDesktop();
     },
 
     hide: function() {
-        this.parent();
+        this._workspacesDisplay.hide();
+    },
+
+    _addTab: function(tab) {
+        tab.page.hide();
+        this._pageArea.add_actor(tab.page);
+        tab.connect('activated', Lang.bind(this, function(tab) {
+            this._switchTab(tab);
+        }));
+    },
+
+    _addViewTab: function(viewTab) {
+        this._tabs.push(viewTab);
+        this._addTab(viewTab);
+    },
+
+    _switchTab: function(tab) {
+        let firstSwitch = this._activeTab == null;
+
+        if (this._activeTab && this._activeTab.visible) {
+            if (this._activeTab == tab)
+                return;
+            this._activeTab.hide();
+        }
+
+        if (tab != this._searchTab) {
+            this._activeTab = tab;
+            if (this._searchTab.visible) {
+                this._searchTab.hide();
+            }
+        }
+
+        // Only fade when switching between tabs,
+        // not when setting the initially selected one.
+        if (!tab.visible)
+            tab.show(!firstSwitch);
+    },
+
+    switchTab: function(id) {
+        for (let i = 0; i < this._tabs.length; i++)
+            if (this._tabs[i].id == id) {
+                this._switchTab(this._tabs[i]);
+                break;
+            }
+    },
+
+    _resetShowAppsButton: function() {
+        this._showAppsButton.checked = false;
+    },
+
+    _onStageKeyPress: function(actor, event) {
+        let modifiers = event.get_state();
+        let symbol = event.get_key_symbol();
+
+        if (symbol == Clutter.Escape) {
+            if (this.active)
+                this.reset();
+            else
+                Main.overview.hide();
+            return true;
+        } else if (Clutter.keysym_to_unicode(symbol) ||
+                   (symbol == Clutter.BackSpace && this.active)) {
+            this.startSearch(event);
+        } else if (!this.active) {
+            if (symbol == Clutter.Tab) {
+                this._activeTab.page.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
+                return true;
+            } else if (symbol == Clutter.ISO_Left_Tab) {
+                this._activeTab.page.navigate_focus(null, Gtk.DirectionType.TAB_BACKWARD, false);
+                return true;
+            }
+        }
+        return false;
+    },
+
+    _searchCancelled: function() {
+        this._switchTab(this._activeTab);
 
         // Leave the entry focused when it doesn't have any text;
         // when replacing a selected search term, Clutter emits
@@ -224,16 +367,6 @@ const SearchTab = new Lang.Class({
         }
     },
 
-    addSearchProvider: function(provider) {
-        this._searchSystem.registerProvider(provider);
-        this._searchResults.createProviderMeta(provider);
-    },
-
-    removeSearchProvider: function(provider) {
-        this._searchSystem.unregisterProvider(provider);
-        this._searchResults.destroyProviderMeta(provider);
-    },
-
     startSearch: function(event) {
         global.stage.set_key_focus(this._text);
         this._text.event(event, false);
@@ -260,14 +393,14 @@ const SearchTab = new Lang.Class({
                         this.reset();
                     }));
             }
-            this._activate();
+            this._switchTab(this._searchTab);
         } else {
             if (this._iconClickedId > 0)
                 this._entry.disconnect(this._iconClickedId);
             this._iconClickedId = 0;
 
             this._entry.set_secondary_icon(this._inactiveIcon);
-            this.emit('search-cancelled');
+            this._searchCancelled();
         }
         if (!this.active) {
             if (this._searchTimeoutId > 0) {
@@ -288,6 +421,15 @@ const SearchTab = new Lang.Class({
                 this.reset();
                 return true;
             }
+        } else if (symbol == Clutter.Return || symbol == Clutter.KP_Enter) {
+            // We can't connect to 'activate' here because search providers
+            // might want to do something with the modifiers in activateDefault.
+            if (this._searchTimeoutId > 0) {
+                Mainloop.source_remove(this._searchTimeoutId);
+                this._doSearch();
+            }
+            this._searchResults.activateDefault();
+            return true;
         } else if (this.active) {
             let arrowNext, nextDirection;
             if (entry.get_text_direction() == Clutter.TextDirection.RTL) {
@@ -337,191 +479,17 @@ const SearchTab = new Lang.Class({
         let text = this._text.get_text().replace(/^\s+/g, '').replace(/\s+$/g, '');
         this._searchResults.doSearch(text);
 
-        return false;
-    }
-});
-
-
-const ViewSelector = new Lang.Class({
-    Name: 'ViewSelector',
-
-    _init : function(searchEntry, showAppsButton) {
-        this.actor = new St.BoxLayout({ name: 'viewSelector',
-                                        vertical: true });
-
-        this._showAppsButton = showAppsButton;
-        this._showAppsButton.connect('notify::checked', Lang.bind(this,
-            function() {
-                if (this._showAppsButton.checked)
-                    this._switchTab(this._appsTab);
-                else
-                    this._switchTab(this._windowsTab);
-            }));
-
-        // The page area holds the tab pages. Every page is given the
-        // area's full allocation, so that the pages would appear on top
-        // of each other if the inactive ones weren't hidden.
-        this._pageArea = new Shell.Stack();
-        this.actor.add(this._pageArea, { x_fill: true,
-                                         y_fill: true,
-                                         expand: true });
-
-        this._tabs = [];
-        this._activeTab = null;
-
-        this._searchTab = new SearchTab(searchEntry);
-        this._addTab(this._searchTab);
-
-        this._searchTab.connect('search-cancelled', Lang.bind(this,
-            function() {
-                this._switchTab(this._activeTab);
-            }));
-
-        this._workspacesDisplay = new WorkspacesView.WorkspacesDisplay();
-        this._windowsTab = new ViewTab('windows', _("Windows"), this._workspacesDisplay.actor, 'text-x-generic');
-        this._addViewTab(this._windowsTab);
-
-        let appView = new AppDisplay.AllAppDisplay();
-        this._appsTab = new ViewTab('applications', _("Applications"), appView.actor, 'system-run');
-        this._addViewTab(this._appsTab);
-
-        // Default search providers
-        // Wanda comes obviously first
-        this.addSearchProvider(new Wanda.WandaSearchProvider());
-        this.addSearchProvider(new AppDisplay.AppSearchProvider());
-        this.addSearchProvider(new AppDisplay.SettingsSearchProvider());
-        this.addSearchProvider(new PlaceDisplay.PlaceSearchProvider());
-        
-        // Load remote search providers provided by applications
-        RemoteSearch.loadRemoteSearchProviders(Lang.bind(this, this.addSearchProvider));
-
-        Main.overview.connect('item-drag-begin',
-                              Lang.bind(this, this._resetShowAppsButton));
-
-        this._stageKeyPressId = 0;
-        Main.overview.connect('showing', Lang.bind(this,
-            function () {
-                this._resetShowAppsButton();
-                this._stageKeyPressId = global.stage.connect('key-press-event',
-                                                             Lang.bind(this, this._onStageKeyPress));
-            }));
-        Main.overview.connect('hiding', Lang.bind(this,
-            function () {
-                this._resetShowAppsButton();
-                if (this._stageKeyPressId != 0) {
-                    global.stage.disconnect(this._stageKeyPressId);
-                    this._stageKeyPressId = 0;
-                }
-            }));
-
-        // Public constraints which may be used to tie actors' height or
-        // vertical position to the current tab's content; as the content's
-        // height and position depend on the view selector's style properties
-        // (e.g. font size, padding, spacing, ...) it would be extremely hard
-        // and ugly to get these from the outside. While it would be possible
-        // to use position and height properties directly, outside code would
-        // need to ensure that the content is properly allocated before
-        // accessing the properties.
-        this.constrainHeight = new Clutter.BindConstraint({ source: this._pageArea,
-                                                            coordinate: Clutter.BindCoordinate.HEIGHT });
-    },
-
-    show: function() {
-        this._workspacesDisplay.show();
-
-        if (!this._workspacesDisplay.activeWorkspaceHasMaximizedWindows())
-            Main.overview.fadeOutDesktop();
-    },
-
-    zoomFromOverview: function() {
-        this._workspacesDisplay.zoomFromOverview();
-
-        if (!this._workspacesDisplay.activeWorkspaceHasMaximizedWindows())
-            Main.overview.fadeInDesktop();
-    },
-
-    hide: function() {
-        this._workspacesDisplay.hide();
-    },
-
-    _addTab: function(tab) {
-        tab.page.hide();
-        this._pageArea.add_actor(tab.page);
-        tab.connect('activated', Lang.bind(this, function(tab) {
-            this._switchTab(tab);
-        }));
-    },
-
-    _addViewTab: function(viewTab) {
-        this._tabs.push(viewTab);
-        this._addTab(viewTab);
-    },
-
-    _switchTab: function(tab) {
-        let firstSwitch = this._activeTab == null;
-
-        if (this._activeTab && this._activeTab.visible) {
-            if (this._activeTab == tab)
-                return;
-            this._activeTab.hide();
-        }
-
-        if (tab != this._searchTab) {
-            this._activeTab = tab;
-            if (this._searchTab.visible) {
-                this._searchTab.hide();
-            }
-        }
-
-        // Only fade when switching between tabs,
-        // not when setting the initially selected one.
-        if (!tab.visible)
-            tab.show(!firstSwitch);
-    },
-
-    switchTab: function(id) {
-        for (let i = 0; i < this._tabs.length; i++)
-            if (this._tabs[i].id == id) {
-                this._switchTab(this._tabs[i]);
-                break;
-            }
-    },
-
-    _resetShowAppsButton: function() {
-        this._showAppsButton.checked = false;
-    },
-
-    _onStageKeyPress: function(actor, event) {
-        let modifiers = event.get_state();
-        let symbol = event.get_key_symbol();
-
-        if (symbol == Clutter.Escape) {
-            if (this._searchTab.active)
-                this._searchTab.reset();
-            else
-                Main.overview.hide();
-            return true;
-        } else if (Clutter.keysym_to_unicode(symbol) ||
-                   (symbol == Clutter.BackSpace && this._searchTab.active)) {
-            this._searchTab.startSearch(event);
-        } else if (!this._searchTab.active) {
-            if (symbol == Clutter.Tab) {
-                this._activeTab.page.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
-                return true;
-            } else if (symbol == Clutter.ISO_Left_Tab) {
-                this._activeTab.page.navigate_focus(null, Gtk.DirectionType.TAB_BACKWARD, false);
-                return true;
-            }
-        }
         return false;
     },
 
     addSearchProvider: function(provider) {
-        this._searchTab.addSearchProvider(provider);
+        this._searchSystem.registerProvider(provider);
+        this._searchResults.createProviderMeta(provider);
     },
 
     removeSearchProvider: function(provider) {
-        this._searchTab.removeSearchProvider(provider);
+        this._searchSystem.unregisterProvider(provider);
+        this._searchResults.destroyProviderMeta(provider);
     }
 });
 Signals.addSignalMethods(ViewSelector.prototype);